import threading
import serial
import time
import os
from pack_message import pack_message
from unpack_message import unpack_message
from progress_bar import progress_bar_manager
from log import write_time_to_file,Write_log
RE_BEGIN_TIME_MAX=15        #begin 开始握手的时候最大次数
RE_TRAN_TIME_MAX=3         #失败重传的次数，表示的是每次传输过程中出现error返回码时出的错误
FILE_BLOCK_SIZE=512        #定义文件读取每次读取的文件块大小
RE_TRAN_FILE_BLOCK_MAX=3   #设置的重传文件块的最大次数
WAIT_CORRECT_DARA_MAX_TIME = 3 #设置等待正确应答的最大时间，如果没到这个时间就一直等待接收

class serial_rec_send():                              #这个实现的是串口收发消息的函数
    def __init__(self,port,baudrate,write_timeout):
        self.port=port
        self.baudrate=baudrate
        self.write_timeout=write_timeout
        self.flag=0                 #标志位---------
        self.temp_serial=serial.Serial(port=self.port,baudrate=self.baudrate,timeout=self.write_timeout)
        self.log=Write_log("{}transmission.log".format(self.port))
    def close(self):
        try:
            self.temp_serial.close()
        except Exception as e:
            print("the device port is closed\n")

    def send_message(self,message):
        try:
            self.temp_serial.write(message)
        except Exception as e:
            print("error:"+e)

    def revice(self):
        thread1=threading.Thread(target=self.create_revice,args=("t1",))
        thread1.start()

    def create_revice(self,threadname):
        while True:
            time.sleep(0.1)
            data=self.temp_serial.readall()
            print(data.decode('utf-8',errors='ignore'))
            self.send_message(data.decode('utf-8',errors='ignore'))

    def is_data(self,data):           #判断data是否符合规矩
        if len(data)!=5:
            return 0
        if data[0]!=0x05:         #如果想要直接判断的话需要使用打包函数进行打包
            return 0
        if data[1]!=0x05:
            return 0
        if data[2]!=0x0A:
            return 0
        if data[3]!=0x0A:
            return 0
        if data[4]==0x00:
            return 1
        return 0

    def file_send(self,filepath,success_times):           #发送文件
        filename=os.path.split(filepath)
        file_type=os.path.splitext(filename[-1])
        if file_type[1].upper() in (".PAC",".BIN"):
            self.flag=0
            self.log.write_log("串口———— {} ————文件开始传输----------\n".format(self.port))
            for i in range(RE_TRAN_TIME_MAX):
                start_time=time.time()
                self.flag=self.file_block_send(filepath,success_times)
                end_time=time.time()
                write_time_to_file(self.port,end_time-start_time)
                if self.flag == 0:
                    continue
                else:
                    break
            if self.flag==1:
                self.log.write_log("串口———— {} ——————传输文件次数：第 {} 已经传输完成-----------\n".format(self.port,success_times))
            else:
                self.log.write_log("串口———— {} ——————传输文件次数：第 {} 超过最大传输次数: {} --文件传输失败\n".format(self.port,success_times,RE_TRAN_TIME_MAX))
        else:
            print("文件类型与所需镜像.pac or .bin 文件不符合\n")

    def file_block_send(self,filepath,success_times):
        pack_tool = pack_message(0x00, None, 0)
        begin_size = pack_tool.get_packed_message()
        self.send_message(begin_size)     #发送复位信号

        pack_tool=pack_message(0x01,None,0)          #打包工具
        begin_size=pack_tool.get_packed_message()
        temp_times=0           #每次重发失败的，这个是记录重发次数的
        start_wait = time.time()
        while True:     #获取串口刚开始的起始位只
            self.send_message(begin_size)
            temp_times+=1
            #设置超时时间，超过这个时间即重新发送即可
            data=self.temp_serial.read(5)      #超时重发时间在这里面直接设置的有，而不是根据变量的定时器进行发送的.......
            if data:
                self.log.write_log("{} : -------the code between the begin is: {}\n".format(self.port,data))
                if self.is_data(data):
                    break
            else:
                self.log.write_log("{} : -------此次data为空\n".format(self.port))
            end_wait=time.time()
            if end_wait-start_wait>WAIT_CORRECT_DARA_MAX_TIME:
                self.log.write_log("{} : -------超过等待正确串口回复的时候最大时间\n".format(self.port))
                return 0
            self.log.write_log("{} : the package begin handshake retransimit-------------\n".format(self.port))
        file=open(filepath,'rb')
        message=file.read(FILE_BLOCK_SIZE)      #每次读取设置的文件块大小
        pack_tool.updata(0x02,message,len(message))
        self.log.write_log("{} : 握手结束————————文件开始传输——————————\n".format(self.port))
        temp_num=1
        file_re_time=0
        while message:
            data=None
            self.send_message(pack_tool.get_packed_message())
            data=self.temp_serial.read(5)
            file_re_time+=1
            if data:
                if not self.is_data(data):       #返回error的话就需要重新开始传输
                    self.log.write_log("{} : the file_block num {} code: {} ,has got ? No\n".format(self.port,temp_num, data))
                    self.log.write_log("-----------------------------------------------------------------------------------------------")
                    self.log.write_log("-----------------------------------------------------------------------------------------------")
                    self.log.write_log("{} : the file is retransmit\n".format(self.port))
                    return 0
                else:                   #返回 OK 的话就需要传输下一个文件块了
                    #self.log.write_log("{} : the file_block num {} code: {} ,has got ? Yes\n".format(self.port,temp_num,data))
                    progress_bar_manager.update(self.port,temp_num,success_times)
                    temp_num+=1
                    message=file.read(FILE_BLOCK_SIZE)
                    pack_tool.updata(0x02,message,len(message))
                    file_re_time=0                                   #一个文件块传输成功的时候就将重传计时块重置为 0
                    continue
            if file_re_time>RE_TRAN_FILE_BLOCK_MAX:
                return 0
            self.log.write_log("{} : the file_block num {} is timeout, has retransimit---------------\n".format(self.port,temp_num))
        pack_tool.updata(0x03,None,0)
        self.log.write_log("{} : 文件传输结束————————等待握手结束——————————\n".format(self.port))
        temp_time=0
        while True:             #最后收到结束后的信息后即可
            self.send_message(pack_tool.get_packed_message())
            temp_time+=1
            data = self.temp_serial.read(5)       #将超时计数器直接放在这边即可
            if data:
                self.log.write_log("{} : the code between end is: {}\n".format(self.port,data))
                if self.is_data(data):
                    break
            if temp_time>RE_BEGIN_TIME_MAX:
                return 0
            self.log.write_log("{} : the package block end is timeout , has retransimit---------\n".format(self.port))
        return 1


    def get_flag(self):
        return self.flag

    def get_port(self):
        return self.port
